/** Name:ConvertInstance.java
 *  
 *  @author: Sunny Toor
 * 
 */
import org.w3c.dom.*;

import javax.xml.parsers.*;

import java.io.*;

import javax.xml.parsers.*;
import org.ands.rifcs.base.*;
import org.xml.sax.SAXException;

import java.util.Date;
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Enumeration;

/**
 * 
 * <b>Description:</b><br/>This class converts an XML instance schema file to a corresponding RIF-CS document.
 * Since this is the first version, it makes a number of assumptions and in case of 
 * insufficient information, it adheres to a default behaviour. This default behaviour
 * can be changed according to the business needs.
 * <br/> <br/><b>Terminology:</b><br/> Source schema refers to the XML schema which needs to be
 * 		mapped to RIF-CS. 
 * <br/><br/><b>Last modified:</b><br/> 9th September 2011
 *
 * @author Sunny Toor
 *
 */
public class ConvertInstance  {

	/** contains crosswalk/mapping from an XML to RIF-CS */
	private Hashtable<String,String> crossWalk = null;
	
	/** Contains elements of the source schema  */
	private ArrayList<String> instance = null;
	
	/** List of all the attributes of the source schema's elements */
	private Hashtable<String,ArrayList<String>> instanceAttr = null;
	
	/** List of all the text values of the source schema's elements */
	private Hashtable<String,ArrayList<String>> instanceText = null;
	
	/** List of all the RIFCS elements */
	private RIFCSElement[] rifcsElements = null; //dont need it
	
	/** RIFCS Wrapper */
	private RIFCSWrapper mw = null;
	
	/** RIFCS Objects */
	private static RIFCS rifcs = null;
	
	/** List of RegistryObjects */
	private ArrayList<RegistryObject> regObjList = null;
	
	/** List of Activities  */
	private ArrayList<Activity> activityList = null;
	
	/** List of Collections */
	private ArrayList<Collection> collectionList = null;
	
	/** List of Parties */
	private ArrayList<Party> partyList = null;
	
	/** List of Services */
	private ArrayList<Service> serviceList = null;
	
	/** List of Identifiers */
	private ArrayList<Identifier> identifierList = null;
	
	/** List of Names */
	private ArrayList<Name> nameList = null;
	
	/** List of Name Parts  */
	private ArrayList<NamePart> namePartList = null;
	
	/** List of Locations */
	private ArrayList<Location> locationList = null;
	
	/** List of Addresses */
	private ArrayList<Address> addressList = null;
	
	/** List of Electronic addresses */
	private ArrayList<Electronic> electronicList = null;
	
	/** List of Args */
	private ArrayList<Arg> argList = null;
	
	/** List of Physical */
	private ArrayList<Physical> physicalList = null;
	
	/** List of AddressParts */
	private ArrayList<AddressPart> addressPartList = null;
	
	/** List of Spatial address parts */
	private ArrayList<Spatial> spatialList = null;
	
	/** List of RelatedObjects */
	private ArrayList<RelatedObject> relatedObjList = null;
	
	/** List of Relations */
	private ArrayList<Relation> relationList = null;
	
	/** List of Descriptions */
	private ArrayList<Description> descriptionList = null;
	
	/** List of Subjects */
	private ArrayList<Subject> subjectList = null;
	
	/** List of Coverages */
	private ArrayList<Coverage> coverageList = null;
	
	/** List of Temporal addresses */
	private ArrayList<Temporal> temporalList = null;
	
	/** List of Temporal Coverage Dates */
	private ArrayList<TemporalCoverageDate> dateList = null;
	
	/** List of Texts */
	private ArrayList<Text> textList = null;
	
	/** List of CitationInfos */
	private ArrayList<CitationInfo> citationInfoList = null;
	
	/** List of CitationMetadatas */
	private ArrayList<CitationMetadata> citationMetadataList = null;
	
	/** List of Contributors */
	private ArrayList<Contributor> contributorList = null;
	
	/** List of CitationDates */
	private ArrayList<CitationDate> citationDateList = null;
	
	/** List of RelatedInfos */
	private ArrayList<RelatedInfo> relatedInfoList = null;
	
	/** List of AccessPolicies */
	private ArrayList<AccessPolicy> accessPolicyList = null;
	
	
	//create 29 data structures one for each RIFCSElement 
	//populate them in one method
	//create appropriate structure in other method.
	
	//construct an array of RIFCSElement objects (superclass of all the rifcs elements objects
	//extract all the information from MODS XML i.e. elements & their texts, attributes & their values
	//for every element in MODS, look up corresponding element in crosswalk hashtable
	//foreach e(new element obtained from crosswalk), create an object(implement a method
	//which will have if-elses for each type of rifcs element
	//
	//try to automate as much as possible with the information obtained from MODS schema
	//if cant do it, then ONLY for mandatory elements, ask the user for input. 
	
	/** 
	 *  <b>Description:</b><br/> Constructs an object of this class.
	 *  It initialises the lists of 29 RIF-CS elements. Description of these 29 elements can 
	 *  be found here: http://services.ands.org.au/documentation/rifcs/java-api-1.2/javadoc/org/ands/rifcs/base/RIFCSElement.html
	 *  
	 *  It also initialises the pre-requisite data-structure needed for successful creation of a valid RIF-CS XML.
	 *  
	 *  <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 *  
	 *  @author Sunny Toor
	 *  
	 *  @param none
	 *  
	 *  @return none
	 *  
	 *  @exception File IO exception
	 *  
	 *  
	 */
	public ConvertInstance() throws Exception{
		// TODO Auto-generated constructor stub
		ReadSavedMapping m = new ReadSavedMapping();
		//FIXME need to fix this in the future & remove the hard-coding.
		crossWalk = m.getCrossWalk("mapping.txt");
		
		rifcsElements = new RIFCSElement[29];

		instance = new ArrayList<String>();
		instanceAttr = new Hashtable<String,ArrayList<String>>();
		instanceText = new Hashtable<String,ArrayList<String>>();
		
		mw = new RIFCSWrapper();
		rifcs = mw.getRIFCSObject();
		
		regObjList = new ArrayList<RegistryObject>();
		activityList = new ArrayList<Activity>();
		collectionList = new ArrayList<Collection>();
		partyList = new ArrayList<Party>();
		serviceList = new ArrayList<Service>();
		identifierList = new ArrayList<Identifier>();
		nameList = new ArrayList<Name>();
		namePartList = new ArrayList<NamePart>();
		locationList = new ArrayList<Location>();
		addressList = new ArrayList<Address>();
		electronicList = new ArrayList<Electronic>();
		argList = new ArrayList<Arg>();
		physicalList = new ArrayList<Physical>();
		addressPartList = new ArrayList<AddressPart>();
		spatialList = new ArrayList<Spatial>();
		relatedObjList = new ArrayList<RelatedObject>();
		relationList = new ArrayList<Relation>();
		descriptionList = new ArrayList<Description>();
		subjectList = new ArrayList<Subject>();
		coverageList = new ArrayList<Coverage>();
		temporalList = new ArrayList<Temporal>();
		dateList = new ArrayList<TemporalCoverageDate>();
		textList = new ArrayList<Text>();
		citationInfoList = new ArrayList<CitationInfo>();
		citationMetadataList = new ArrayList<CitationMetadata>();
		contributorList = new ArrayList<Contributor>();
		citationDateList = new ArrayList<CitationDate>();
		relatedInfoList = new ArrayList<RelatedInfo>();
		accessPolicyList = new ArrayList<AccessPolicy>();
		
	}
	
	/** 
	 * <b>Description:</b><br/> Iterates through any list and concatenates all its elements into a string
	 * separated by separator
	 * 
	 * <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 * 
	 * @author Sunny Toor
	 * 
	 * @param   
	 * 
	 * @return concatenated elements of the list separated by the <i>separator</i>
	 *
	 * @exception File IO exception
	 * 
	 */
	public String iterateList(ArrayList<String> aList, String separator){
		String result = "";
		if(aList != null){
			for(Iterator<String> e = aList.iterator(); e.hasNext();){
				result += e.next() + separator;
			}
		}
		return result;
	}
	
	
	/** 
	 * 
	 * <b>Description:</b><br/> This is the method that populates the lists of 29 RIF-CS elements. 
	 *		While populating each RIF-CS element (from other schema's elements), a lot of 
	 *		assumptions are made. In case of insufficient information, most of the RIF-CS elements'
	 *		<i>type</i> and <i>description</i> are filled. For RIF-CS elements that do not support 
	 *		<i>type</i> and <i>description</i>, other default tags are automatically initialised. 
	 *		However, this behaviour can be (or should be?) changed in the next version of the software. 
	 *		Also, in case an element was not mapped to any RIF-CS element, a default 'collection' object 
	 *		is created for it. This default behaviour too can be changed in the future.  
	 *
	 * <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 * 
	 * @author Sunny Toor
	 * @param an output printstream 
	 * @return none
	 * @exception File IO exception	
	 * 		
	 */
	public void populateDataStrucures(PrintStream out) throws Exception{
		if(instance.isEmpty()){
			System.err.println("Error: Instance data structure not initialised.");
			System.exit(0);
		}
		
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		out.println("Specify Group: ");
		String group = in.readLine();
		out.println("Specify prefix/suffix for unique keys, for eg: name of the organisation: ");
		String key_suffix = in.readLine();
		out.println("Specify the originating source: ");
		String originating_source = in.readLine();
		
		//Registry Object
		RegistryObject r = rifcs.newRegistryObject();
		long time = System.currentTimeMillis();
		String uniq_key = time+"_"+key_suffix;
		r.setKey(uniq_key);
		r.setGroup(group);
		r.setOriginatingSource(originating_source);
		
		//Collection
		Collection collection = r.newCollection();
		Service service = r.newService();
		
		//Initialise all the objects needed 
		Activity activity = r.newActivity();
		//Collection collec = r.newCollection();
		Party party = r.newParty();
		
		Identifier identifier = collection.newIdentifier();
		Name name = collection.newName();
		NamePart np = name.newNamePart();
		Location loc = collection.newLocation();
		Address add = loc.newAddress();
		Electronic elec = add.newElectronic();
		Arg arg = elec.newArg();
		Physical physical = add.newPhysical();
		AddressPart addPart = physical.newAddressPart();
		Spatial spatial = loc.newSpatial();
		RelatedObject relatedObj = collection.newRelatedObject();
		Relation relation = relatedObj.newRelation();
		Subject subject = collection.newSubject();
		Description desc = collection.newDescription();
		Coverage coverage = collection.newCoverage();
		Temporal temporal = coverage.newTemporal();
		TemporalCoverageDate temporalDate = temporal.newDate();
		CitationInfo citationInfo = collection.newCitationInfo();
		CitationMetadata citationMetadata = citationInfo.newCitationMetadata();
		Contributor contributor = citationMetadata.newContributor();
		CitationDate citationDate = citationMetadata.newCitationDate();
		RelatedInfo relatedInfo = collection.newRelatedInfo();
		AccessPolicy accessPolicy = service.newAccessPolicy();
		
		
		for(Iterator<String> i = instance.iterator() ; i.hasNext();){
			String instance_element = i.next(); // other schema element
			out.println(instance_element);
			String rifcs_element = crossWalk.get(instance_element); //rifcs element
			
			ArrayList<String> attributes = null;
			ArrayList<String> text = null;
			
			if(instanceAttr.containsKey(instance_element)){
				attributes = instanceAttr.get(instance_element);
			}
			if(instanceText.containsKey(instance_element)){
				text = instanceText.get(instance_element);
			}
			
			if(rifcs_element.equals("Activity")){
				activity = r.newActivity();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				Description dsc = activity.newDescription();
				dsc.setValue(txt);
				
				//TODO: default is setting type and description 
				//		change later.
				activity.setType(attr);
				activity.addDescription(dsc);
				
				activityList.add(activity);
			}
			else if(rifcs_element.equals("Collection")){
				collection = r.newCollection();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and description 
				//		change later.
				collection.setType(attr);
				collection.addDescription(txt, "brief", "lang-eng");
				
				collectionList.add(collection);
			}
			else if(rifcs_element.equals("Party")){
				party = r.newParty();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				Description dsc = party.newDescription();
				dsc.setValue(txt);
				
				//TODO: default is setting type and description 
				//		change later.
				party.setType(attr);
				party.addDescription(dsc);
				
				partyList.add(party);
			}
			else if(rifcs_element.equals("Service")){
				service = r.newService();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				Description dsc = service.newDescription();
				dsc.setValue(txt);
				
				//TODO: default is setting type and description 
				//		change later.
				service.setType(attr);
				service.addDescription(dsc);
				
				serviceList.add(service);
			}
			else if(rifcs_element.equals("Identifier")){
				identifier = collection.newIdentifier();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and value 
				//		change later.
				identifier.setType(attr);
				identifier.setValue(txt);
				
				identifierList.add(identifier);
			}
			else if(rifcs_element.equals("Name")){
				name = collection.newName();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and name part. 
				//		change later.
				name.setType(attr);
				name.addNamePart(txt, "first");
				
				nameList.add(name);
				
			}
			else if(rifcs_element.equals("NamePart")){
				np = name.newNamePart();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and value. 
				//		change later.
				np.setType(attr);
				np.setValue(txt);
				
				namePartList.add(np);
			}
			else if(rifcs_element.equals("Location")){
				loc = collection.newLocation();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting dateFrom and dateTo. 
				//		change later.
				loc.setDateFrom(attr);
				loc.setDateTo(txt);
				
				locationList.add(loc);
			}
			else if(rifcs_element.equals("Address")){
				add = loc.newAddress();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting dateFrom and dateTo. 
				//		change later.
				loc.setDateFrom(attr);
				loc.setDateTo(txt);
				
				addressList.add(add);
			}
			else if(rifcs_element.equals("Electronic")){
				elec = add.newElectronic();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text, ". ");
				
				//TODO: default is setting type and value. 
				//		change later.
				elec.setType(attr);
				elec.setValue(txt);
				
				electronicList.add(elec);
			}
			else if(rifcs_element.equals("Arg")){
				arg = elec.newArg();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text, ". ");
				
				//TODO: default is setting type and use. 
				//		change later.
				arg.setType(attr);
				arg.setUse(txt);
				
				argList.add(arg);
			}
			else if(rifcs_element.equals("Physical")){
				physical = add.newPhysical();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and language. 
				//		change later.
				physical.setType(attr);
				physical.setLanguage(txt);
				
				physicalList.add(physical);
			}
			else if(rifcs_element.equals("AddressPart")){
				addPart = physical.newAddressPart();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and value. 
				//		change later.
				addPart.setType(attr);
				addPart.setValue(txt);
				
				addressPartList.add(addPart);
			}
			else if(rifcs_element.equals("Spatial")){
				spatial = loc.newSpatial();
				String attr = iterateList(attributes, "");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and value. 
				//		change later.
				spatial.setType(attr);
				spatial.setValue(txt);
				
				spatialList.add(spatial);
			}
			else if(rifcs_element.equals("RelatedObject")){
				relatedObj = collection.newRelatedObject();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting relation and key. 
				//		change later.
				relatedObj.addRelation(attr, "default", txt, "eng");
				relatedObj.setKey(txt);
				
				relatedObjList.add(relatedObj);
			}
			else if(rifcs_element.equals("Relation")){
				relation = relatedObj.newRelation();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and description. 
				//		change later.
				relation.setType(attr);
				relation.setDescription(txt);
				relation.setDescriptionLanguage("eng");
				
				relationList.add(relation);
			}
			else if(rifcs_element.equals("Description")){
				desc = collection.newDescription();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and value. 
				//		change later.
				desc.setType(attr);
				desc.setValue(txt);
				
				descriptionList.add(desc);
			}
			else if(rifcs_element.equals("Subject")){
				subject = collection.newSubject();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting type and value. 
				//		change later.
				subject.setType(attr);
				subject.setValue(txt);
				
				subjectList.add(subject);
			}
			else if(rifcs_element.equals("Coverage")){
				coverage = collection.newCoverage();
				String attr = iterateList(attributes, "");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting temporal date
				//		Change later.
				coverage.addTemporalDate(txt, attr, "DD/MM/YYYY");
				
				coverageList.add(coverage);
			}
			else if(rifcs_element.equals("Temporal")){
				temporal = coverage.newTemporal();
				String attr = iterateList(attributes, "");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting date and text.
				//		Change later.
				Date d = new Date();
				String dString = d.toString();
				temporal.addDate(dString, attr, "DD/MM/YYYY");
				temporal.addText(txt);
				temporalList.add(temporal);
			}
			else if(rifcs_element.equals("Date")){
				temporalDate = temporal.newDate();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting date and text.
				//		Change later.
				temporalDate.setType(attr);
				temporalDate.setValue(txt);
				
				dateList.add(temporalDate);
			}
			
			else if(rifcs_element.equals("CitationInfo")){
				citationInfo = collection.newCitationInfo();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text, ". ");
				
				//TODO: default is setting citation.
				//		Change later.
				citationInfo.setCitation(txt, attr);
				
				citationInfoList.add(citationInfo);
			}
			else if(rifcs_element.equals("CitationMetadata")){
				citationMetadata = citationInfo.newCitationMetadata();
				String attr = iterateList(attributes, "");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting context and title.
				//		Change later.
				citationMetadata.setContext(attr);
				citationMetadata.setTitle(txt);
				
				citationMetadataList.add(citationMetadata);
			}
			else if(rifcs_element.equals("Contributor")){
				contributor = citationMetadata.newContributor();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text, ". ");
				
				//TODO: default is setting name part.
				//		Change later.
				contributor.addNamePart(txt, attr);
				
				contributorList.add(contributor);
			}
			else if(rifcs_element.equals("CitationDate")){
				citationDate = citationMetadata.newCitationDate();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting name part.
				//		Change later.
				citationDate.setType(attr);
				citationDate.setValue(txt);
				
				citationDateList.add(citationDate);
			}
			else if(rifcs_element.equals("RelatedInfo")){
				relatedInfo = collection.newRelatedInfo();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting name part.
				//		Change later.
				relatedInfo.setType(attr);
				relatedInfo.setNotes(txt);
				
				relatedInfoList.add(relatedInfo);			
			}
			else if(rifcs_element.equals("AccessPolicy")){
				accessPolicy = service.newAccessPolicy();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting name part.
				//		Change later.
				accessPolicy.setValue(txt);
				
				accessPolicyList.add(accessPolicy);
			}
			else{
				collection = r.newCollection();
				String attr = iterateList(attributes,"");
				String txt = iterateList(text,". ");
				
				//TODO: default is setting name part.
				//		Change later.
				collection.setType(attr);
				collection.addDescription(txt, "brief", "lang-eng");
			
				collectionList.add(collection);
				
			}
			
		}
	}
	//patience resolt *belief*
	//dream, imagine, believe, think, sleep, wake, eat it.
	
	/** 
	 * 
	 * <b>Description:</b><br/> This is the main method which constructs the RIF-CS XML file 
	 * 	from the lists of 29 RIF-CS elements. Any change resulting from the new version 
	 * 	of RIF-CS or due to another reason, would need to be made here. 
	 * 
	 * <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 * 
	 * @author Sunny Toor
	 * @param filename
	 * @return none
	 * @exception File IO exception	
	 * 
	 */
	public void constructRifcsXML(String filename) throws Exception{
		 
	}
	
	/** 
	 * <b>Description:</b><br/> create and return an XML document from a give filename
	 * 
	 * <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 * 
	 * @author Sunny Toor
	 * @param filename
	 * @return an XML document
	 * @exception File IO exception
	 * 
	 */
	public Document getDocReprensation(String fileName)throws Exception {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document doc = db.parse(new File(fileName));
		
		return doc;
	}

	/** 
	 * <b>Description:</b><br/> this method is in-charge of recursively traversing an XML document's
	 * 	tree representation. While traversing each node(element), it extracts all the information from it
	 * 	and stores in the appropriate data-structures to be utilised later.  
	 * 
	 * <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 * 
	 * @author Sunny Toor
	 * @param XML document's node and output print stream
	 * @return N/A
	 * @exception File IO exception
	 * 
	 */
	public void traverseDoc(Node node, PrintStream out) throws Exception{
		if (node == null){
			return;
		}
		int type = node.getNodeType();
		if(type==Node.ELEMENT_NODE){
			
			//traverse the XML instance document 
			//extract all the information for each element 
			String ele = node.toString().replaceAll(".(.*?): null.", "$1");
			if(ele.matches(".*:.*")){
				ele = ele.replaceAll(".*:(.*)", "$1");
			}
			int attLen = node.getAttributes().getLength();

			out.println(ele);
			instance.add(ele);
			
			//Text of the element 
			if(!node.getTextContent().contains("\n") && node.getTextContent()!=""){
				ArrayList<String> tmp;
				if(!instanceText.containsKey(ele)){
					tmp = new ArrayList<String>();
					tmp.add(node.getTextContent());	
				}
				else{
					tmp = instanceText.get(ele);
					tmp.add(node.getTextContent());
				}
				instanceText.put(ele, tmp);
			}
		
			if(attLen>=1){
				String firstAttr = node.getAttributes().item(0).toString();
				//out.println(ele+"  "+firstAttr +"; ");
				ArrayList<String> tmp;
				
				if(!instanceAttr.containsKey(ele)){
					tmp = new ArrayList<String>();
					tmp.add(firstAttr);
				}
				else{
					tmp = instanceAttr.get(ele);
					if(!tmp.contains(firstAttr)){
						tmp.add(firstAttr);
					}
					
				}
				
				//Attributes and their values
				for(int i=1; i<attLen; i++){
					String attribute = node.getAttributes().item(i).toString();
					if(!tmp.contains(attribute)){
						tmp.add(attribute);
					}
				}
				instanceAttr.put(ele, tmp);
				
			}
			
			//out.println();
		}
		NodeList childNodes = node.getChildNodes();
		if(childNodes != null){
			int numOfChilds = childNodes.getLength();
			for(int i=0; i<numOfChilds; i++){
				traverseDoc(childNodes.item(i),out);
			}
		}
	}
	
	/** 
	 * <b>Description:</b><br/> It prints a cross walk (i.e. mapping from a schema to RIF-CS) 
	 * 	to a file. This is useful for client viewing and for any debugging purposes.
	 * 
	 * <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 * 
	 * @author Sunny Toor
	 * @param (a crosswalk and an output print stream)
	 * @return (NA)
	 * @exception (NA)
	 * 
	 */
	public void printMap(Hashtable<String,ArrayList<String>> crossWalk,PrintStream out){
		if(crossWalk.isEmpty()){
			out.println("No elements read from file.");
		}
		else{
			for(Enumeration<String> e = crossWalk.keys(); e.hasMoreElements();){
				String k = e.nextElement();
				ArrayList<String> vals = crossWalk.get(k); //could directly print this
				out.print(k+" :- ");
				Iterator<String> valIterator = vals.iterator();
				while(valIterator.hasNext()){
					out.print(valIterator.next()+"; ");
				}
				
				out.println();
				
			}
		}
	}
	/**
	 * <b>Description:</b><br/> Main method to control this class.
	 * 
	 * <br/><br/><b>Last modified:</b><br/> 28th August 2011
	 * 
	 * @author Sunny Toor
	 * @param args
	 * @return NA
	 * @exception File IO Exception
	 * 
	 */
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		ConvertInstance i = new ConvertInstance();
		Document d = i.getDocReprensation("example1.xml");
		i.traverseDoc(d, System.out);
		//i.printMap(i.instanceText, System.out);
	}

}
